﻿package frEngine.effectEditTool.lineRoad
{
    import __AS3__.vec.*;
    import baseEngine.basic.*;
    import baseEngine.core.*;
    import flash.geom.*;
    import frEngine.effectEditTool.manager.*;
    import frEngine.primitives.base.*;
    import frEngine.shader.*;
    import frEngine.shape3d.*;

    public class LineRoadMesh3D extends LineBase
    {
        private var _curCircleList:Array;
        public var lineList:Vector.<BezierLine>;
        private var _selectedCircle:LineCirle;
        private var _prePos:Vector3D;
        private var _preRot:Vector3D;
        private var totalCacheNum:int = 0;
        private var posCache:Vector.<Vector3D>;
        private var transformCache:Vector.<Matrix3D>;
        private static var _defaultCircleMaterial:ShaderBase;
        private static const _circlePool:Array = new Array();
        private static const defaultPoint:Vector3D = new Vector3D();
        private static const defaultMatrix3d:Matrix3D = new Matrix3D();

        public function LineRoadMesh3D()
        {
            this._curCircleList = new Array();
            this.lineList = new Vector.<BezierLine>;
            this._prePos = new Vector3D();
            this._preRot = new Vector3D();
            super(null, false, null);
            return;
        }// end function

        public function reinit(param1:RenderList) : void
        {
            this.renderList = param1;
            return;
        }// end function

        public function drawLine() : void
        {
            var _loc_4:BezierLine = null;
            var _loc_5:int = 0;
            var _loc_6:int = 0;
            download(false);
            drawInstance.clear();
            drawInstance.lineStyle(1, 16777215, 1);
            var _loc_1:* = new Vector3D();
            var _loc_2:* = this.lineList.length;
            var _loc_3:int = 0;
            while (_loc_3 < _loc_2)
            {
                
                _loc_4 = this.lineList[_loc_3];
                if (_loc_4.isStart)
                {
                    drawInstance.moveTo(_loc_4.P0.x, _loc_4.P0.y, _loc_4.P0.z);
                }
                _loc_5 = _loc_4.total_length / 5;
                _loc_6 = 1;
                while (_loc_6 <= _loc_5)
                {
                    
                    _loc_4.beze(_loc_6 / _loc_5, _loc_1);
                    drawInstance.lineTo(_loc_1.x, _loc_1.y, _loc_1.z);
                    _loc_6++;
                }
                _loc_3++;
            }
            return;
        }// end function

        public function showCircle() : void
        {
            var _loc_2:LineCirle = null;
            var _loc_3:BezierLine = null;
            var _loc_4:BezierLine = null;
            this.clearAllCircle();
            var _loc_1:* = this.lineList.length;
            if (_loc_1 == 0)
            {
                return;
            }
            var _loc_5:int = 0;
            while (_loc_5 < _loc_1)
            {
                
                _loc_4 = this.lineList[_loc_5];
                if (_loc_4.isStart)
                {
                    _loc_3 = _loc_4;
                    _loc_2 = LineRoadMesh3D.createCircle(this, _loc_3.P0, null, _loc_3.P1);
                    this._curCircleList.push(_loc_2);
                    _loc_5++;
                    _loc_4 = _loc_5 < _loc_1 ? (this.lineList[_loc_5]) : (null);
                }
                if (_loc_4)
                {
                    _loc_2 = LineRoadMesh3D.createCircle(this, _loc_3.P3, _loc_3.P2, _loc_4.P1);
                    this._curCircleList.push(_loc_2);
                }
                if (_loc_5 >= (_loc_1 - 1) || this.lineList[(_loc_5 + 1)].isStart)
                {
                    _loc_2 = LineRoadMesh3D.createCircle(this, _loc_3.P3, _loc_3.P2, null);
                    this._curCircleList.push(_loc_2);
                }
                _loc_3 = _loc_4;
                _loc_5++;
            }
            return;
        }// end function

        public function initLine(param1:Array, param2:Number) : void
        {
            var _loc_6:Object = null;
            var _loc_7:Array = null;
            var _loc_8:Boolean = false;
            var _loc_9:int = 0;
            var _loc_10:Object = null;
            var _loc_11:BezierLine = null;
            var _loc_12:int = 0;
            var _loc_13:Object = null;
            var _loc_3:* = param1.length;
            this.lineList.length = 0;
            var _loc_4:Number = 0;
            var _loc_5:int = 0;
            while (_loc_5 < _loc_3)
            {
                
                _loc_6 = param1[_loc_5];
                _loc_7 = _loc_6.pointsList;
                _loc_8 = _loc_6.isClosed;
                _loc_9 = _loc_7.length;
                _loc_10 = _loc_7[0];
                _loc_12 = 1;
                while (_loc_12 < _loc_9)
                {
                    
                    _loc_13 = _loc_7[_loc_12];
                    _loc_11 = new BezierLine(_loc_10.pos, _loc_10.outPos, _loc_13.inPos, _loc_13.pos, _loc_13.len);
                    if (_loc_12 == 1)
                    {
                        _loc_11.isStart = true;
                    }
                    this.lineList.push(_loc_11);
                    _loc_11.startTime = _loc_4 / param2;
                    _loc_11.disTime = _loc_11.total_length / param2;
                    _loc_4 = _loc_4 + _loc_11.total_length;
                    _loc_10 = _loc_13;
                    _loc_12++;
                }
                if (_loc_8)
                {
                    _loc_13 = _loc_7[0];
                    _loc_11 = new BezierLine(_loc_10.pos, _loc_10.outPos, _loc_7[0].inPos, _loc_13.pos, _loc_13.len);
                    this.lineList.push(_loc_11);
                    _loc_11.startTime = _loc_4 / param2;
                    _loc_11.disTime = _loc_11.total_length / param2;
                    _loc_4 = _loc_4 + _loc_11.total_length;
                }
                _loc_5++;
            }
            this.totalCacheNum = int(_loc_4 / 2);
            this.clearCache(true);
            return;
        }// end function

        public function getPosByTime(param1:Number) : Vector3D
        {
            if (this.lineList.length == 0)
            {
                return defaultPoint;
            }
            if (param1 < 0)
            {
                param1 = 0;
            }
            if (param1 > 1)
            {
                param1 = 1;
            }
            param1 = Math.round(param1 * (this.totalCacheNum - 1));
            var _loc_2:* = this.posCache[param1];
            if (_loc_2)
            {
                return _loc_2;
            }
            var _loc_3:* = param1 / this.totalCacheNum;
            _loc_2 = new Vector3D(0, 0, 0, 1);
            var _loc_4:* = this.fastGetInsertPos(this.lineList, _loc_3);
            var _loc_5:* = this.lineList[_loc_4];
            var _loc_6:* = (_loc_3 - _loc_5.startTime) / _loc_5.disTime;
            _loc_5.beze(_loc_6, _loc_2);
            var _loc_7:* = this.world.transformVector(_loc_2);
            _loc_2 = this.world.transformVector(_loc_2);
            this.posCache[param1] = _loc_7;
            return _loc_2;
        }// end function

        public function getMatrix3dByTime(param1:Number) : Matrix3D
        {
            var _loc_5:Vector3D = null;
            var _loc_6:Vector3D = null;
            if (this.lineList.length == 0)
            {
                return defaultMatrix3d;
            }
            if (param1 < 0)
            {
                param1 = 0;
            }
            if (param1 > 1)
            {
                param1 = 1;
            }
            var _loc_2:* = Math.round(param1 * (this.totalCacheNum - 1));
            var _loc_3:* = this.transformCache[_loc_2];
            if (_loc_3)
            {
                return _loc_3;
            }
            var _loc_4:* = this.getPosByTime(param1);
            if (_loc_2 == 0)
            {
                _loc_5 = this.getPosByTime(param1 + 1 / this.totalCacheNum).subtract(_loc_4);
            }
            else if (_loc_2 == (this.totalCacheNum - 1))
            {
                _loc_5 = _loc_4.subtract(this.getPosByTime(param1 - 1 / (this.totalCacheNum - 1)));
            }
            else
            {
                _loc_5 = this.getPosByTime(param1 + 1 / (this.totalCacheNum - 1)).subtract(_loc_4);
            }
            var _loc_8:* = new Matrix3D();
            _loc_3 = new Matrix3D();
            this.transformCache[_loc_2] = _loc_8;
            _loc_5.normalize();
            if (_loc_5.x == 0 && Math.abs(_loc_5.y) == 1 && _loc_5.z == 0)
            {
                _loc_6 = Vector3D.Z_AXIS;
            }
            else
            {
                _loc_6 = Vector3D.Y_AXIS;
            }
            var _loc_7:* = _loc_6.crossProduct(_loc_5);
            _loc_7.normalize();
            _loc_6 = _loc_5.crossProduct(_loc_7);
            var _loc_8:int = 0;
            _loc_5.w = 0;
            var _loc_8:* = _loc_8;
            _loc_6.w = _loc_8;
            _loc_7.w = _loc_8;
            _loc_3.copyColumnFrom(0, _loc_7);
            _loc_3.copyColumnFrom(1, _loc_5);
            _loc_3.copyColumnFrom(2, _loc_6);
            _loc_3.copyColumnFrom(3, _loc_4);
            return _loc_3;
        }// end function

        public function clearCache(param1:Boolean) : void
        {
            this.posCache = new Vector.<Vector3D>(this.totalCacheNum, true);
            if (param1)
            {
                this.transformCache = new Vector.<Matrix3D>(this.totalCacheNum, true);
            }
            return;
        }// end function

        public function fastGetInsertPos(param1:Vector.<BezierLine>, param2:Number) : int
        {
            var _loc_6:Number = NaN;
            var _loc_3:* = param1.length;
            var _loc_4:int = 0;
            var _loc_5:int = -1;
            while (_loc_4 < _loc_3)
            {
                
                _loc_5 = _loc_4 + _loc_3 >>> 1;
                _loc_6 = param1[_loc_5].startTime;
                if (_loc_6 == param2)
                {
                    return _loc_5;
                }
                if (param2 > _loc_6)
                {
                    _loc_4 = _loc_5 + 1;
                    continue;
                }
                _loc_3 = _loc_5 + 1;
            }
            return (_loc_5 - 1);
        }// end function

        public function clearAllCircle() : void
        {
            var _loc_4:LineCirle = null;
            var _loc_1:* = this._curCircleList.length;
            var _loc_2:Array = [];
            var _loc_3:int = 0;
            while (_loc_3 < _loc_1)
            {
                
                _loc_4 = this._curCircleList[_loc_3];
                _loc_4.clear();
                _circlePool.push(_loc_4);
                delete Obj3dContainer.sceneObjectsList[_loc_4];
                _loc_3++;
            }
            this._curCircleList.length = 0;
            return;
        }// end function

        override public function dispose(param1:Boolean = true) : void
        {
            download(false);
            this.clearAllCircle();
            super.dispose(param1);
            return;
        }// end function

        private static function createCircle(param1:Pivot3D, param2:Object, param3:Object, param4:Object) : LineCirle
        {
            var _loc_5:LineCirle = null;
            if (_circlePool.length == 0)
            {
                _loc_5 = new LineCirle(11184810);
            }
            else
            {
                _loc_5 = _circlePool.shift();
            }
            _loc_5.initParent(param1, param2, param3, param4);
            return _loc_5;
        }// end function

    }
}
